#!/bin/sh

SUCCESS=0
FAIL=-1
ERRCODE=-1

# reboot after updated?
NEED_REBOOT=$1

UPD_KERNEL_FILE="/userdata/kernel"
UPD_ROOTFS_FILE="/userdata/rootfs.ext4"

A_KERNEL="/dev/block/mmcblk0p5"
A_ROOTFS="/dev/block/mmcblk0p7"
B_KERNEL="/dev/block/mmcblk0p6"
B_ROOTFS="/dev/block/mmcblk0p8"

UPDATE="toybox dd"
LOG_FILE="/userdata/ota_update_$(date '+%Y%m%d%H%M%S').log"
RUNNING_SLOT=""

BS=512

KERNEL_SIZE=26185
ROOTFS_SIZE=409600

function log() {
    local message="$1"
    echo "$(date '+%Y-%m-%d %H:%M:%S') - ${message}" >> "$LOG_FILE"
}

function get_running() {
	boot_helper setrunning 1>/dev/null
	boot_info=$(boot_helper getinfo)
	
	temp=${boot_info#*boot.running_slot: }
	RUNNING_SLOT=${temp:0:1}
	
	log "running slot: ${RUNNING_SLOT}"

	if [ -z ${RUNNING_SLOT} ]; then
		log "ERROR: no running_slot found."
		return ${FAIL}
	fi
	
	return ${SUCCESS}
}

function check_file() {
	if [ -f ${UPD_KERNEL_FILE} ]; then
		log "kernel found."
	else
		log "ERROR: kernel not found."
		return ${FAIL}
	fi

	if [ -f ${UPD_ROOTFS_FILE} ]; then
		log "rootfs found."
	else
		log "ERROR: rootfs not found."
		return ${FAIL}
	fi
	
	return ${SUCCESS}
}

show_progress() {
    COMPLETED_BYTES=$((COMPLETED_BYTES + SPEED))
    local PERCENT=$(echo "scale=2; $COMPLETED_BYTES / $TOTAL_BYTES * 100" | busybox bc)
	printf "\rProgress: %.0f%%" "$PERCENT"
}

function write_part() {
	local src=$1
	local dst=$2
	local size=$3
	
	TOTAL_BYTES=$((512*${size}))
	COMPLETED_BYTES=0
	# 12M/s->125829/(1/100s)
	SPEED=125829
	
	log "write part ${dst}"
	
	${UPDATE} if=${src} of=${dst} bs=${BS} count=${size} 2>/dev/null &
	DD_PID=$!
	
	while kill -0 "$DD_PID" 2>/dev/null; do
		show_progress
		sleep 0.01
	done

	printf "\rProgress: %.0f%%" 100.00
	printf "\n"

	wait ${DD_PID}
	ERRCODE=$?

	if [ ${ERRCODE} -ne 0 ]; then
		log "ERROR: write part ${src} error. error code：${ERRCODE}"
		return ${ERRCODE}
	else
		log "write part ${dst} success."
	fi
	
	return ${SUCCESS}
}

function do_update() {
	local part=$1
	
	if [ ${part} == "a" ]; then
		local KERNEL=${A_KERNEL}
		local ROOTFS=${A_ROOTFS}
	elif [ ${part} == "b" ]; then
		local KERNEL=${B_KERNEL}
		local ROOTFS=${B_ROOTFS}
	else
		return ${FAIL}
	fi
	
	log "updating system ${part}..."
	
	echo "Updating kernel"
	write_part ${UPD_KERNEL_FILE} ${KERNEL} ${KERNEL_SIZE}
	ERRCODE=$?
	if [ ${ERRCODE} -ne 0 ]; then
		log "ERROR: update kernel_${part} error."
		return ${ERRCODE}
	fi

	echo "Updating rootfs"
	write_part ${UPD_ROOTFS_FILE} ${ROOTFS} ${ROOTFS_SIZE}
	ERRCODE=$?
	if [ ${ERRCODE} -ne 0 ]; then
		log "ERROR: update rootfs_${part} error."
		return ${ERRCODE}
	fi
	
	boot_helper setslot ${part} 1>/dev/null
	ERRCODE=$?
	if [ ${ERRCODE} -ne 0 ]; then
		log "ERROR: boot_helper setslot faild."
		return ${ERRCODE}
	fi
	
	log "update system ${part} success."
	
	if [ "${NEED_REBOOT}" = "reboot" ];then
		echo "Updater success. restarting ..."
		log "restarting ..."
		reboot
	fi
	
	return ${SUCCESS}
}

get_running
if [ $? -ne 0 ]; then
	echo "Updater fail."
	exit ${FAIL}
fi

check_file
if [ $? -ne 0 ]; then
	echo "Updater fail."
	exit ${FAIL}
fi

if [ ${RUNNING_SLOT} = "a" ]; then
	echo "Update system b ..."
	do_update b
	if [ $? -ne 0 ]; then
		echo "Updater fail."
		exit ${FAIL}
	fi
fi

if [ ${RUNNING_SLOT} = "b" ]; then
	echo "Update system a ..."
	do_update a
	if [ $? -ne 0 ]; then
		echo "Updater fail."
		exit ${FAIL}
	fi
fi

echo "Updater success."
exit ${SUCCESS}